查看原文
其他

夜天之书 #18 Evolving Governance

tisonkun 夜天之书 2022-04-06

今天看到一篇文章讲 Kubernetes 社区的运作方式,想复刻一篇旧文分享 Kubernetes 的方案在 TiDB 和 TiKV 社区的采用情况。

Kubernetes 社区是如何运作的?

关于其中的自动化部分,引用已发布文章作为评论。

夜天之书 #8

写在最前,随着开源协同行业经验的积累和从业人员的成熟,最佳实践总是越来越好的。讨论过程中会涉及具体的开源社区案例,早期阶段的案例或多或少有不足之处,大多是时代所限,正是这些前人探索的实例,才构成了今天可以分析和演进的基础。

以下原文,略有修改。

开源社区的治理模型应当因地制宜。

比起开发功能或重构代码,社区治理听起来既不酷也不有趣。

然而,随着社区规模的不断扩大,社区事务日渐增长和复杂,社区成员也期待有专职人员按照明确的规则来协调社区事务的开展,这其实就是治理模型的一部分。

本文以 TiDB 和 TiKV 两个开源社区重新评估自己的治理模型的近期动作为契机,通过介绍它们所面临的问题和采取的应对手段,希望能为如雨后春笋般增长的新兴开源社区提供开源社区的治理模型方面的经验。这里面最重要的一条就是,开源社区的治理模型应当因地制宜。

不要以为这一点如同它乍一看上去那么自然。Ubuntu 的社区经理 Jono Bacon 在他的著作《社区运营的艺术》[1]中,不少于两次提及形式主义的社区流程与治理模型的危害,这其实与本文标题所主张的观点是相通的。我们先看到具体的例子,再回头讨论抽象上的问题。

Problem

TiKV 社区在几年为重组其治理模型展开了一系列行动。

Proposal: Reduce the Entropy of TiKV Community Governance[2]

除了一开始跟社区成员的线下沟通以形成对问题的归纳以外,行动的背景和实际采取的手段都可以在上面的提案中追溯到讨论的过程和详细的介绍。

TiKV 社区遇到的问题可以分为三个方面,分别是项目代码仓库的权限模型不清晰,Special Interest Group 治理模型的失败,以及从未起过实际作用的 Working Group 机制。

Repository

提案原文写到

Most of our repositories have no clear owners; for example, it is hard to say who has review or commit permission of mur3 by our governance and community information.

实际上,TiKV 项目里几乎只有 tikv/tikv[3]tikv/raft-rs[4] 和 tikv/pd[5] 三个仓库是纳入社区治理的考量范围的,其他四十几个仓库无人管理,没人能说得清谁是负责人甚至相关人员。

一方面,这会伤害到贡献 TiKV 社区里其他开源项目的成员,例如被广泛使用的 tikv/rust-prometheus[6] 和 tikv/client-java[7] 等等。另一方面,社区的新成员完全对如何参与这些项目的贡献没有眉目。尤其是几次一时兴起的社区流程自动化运动遗留下来的机器人及其机制,使得每个项目的代码合并流程甚至连部落知识都没有。

Special Interest Group

SIG 这个概念在学术界早已有之且久负盛名,在开源社区将 SIG 的概念发扬光大的要数 Kubernetes 社区。关于 Kubernetes 社区的问题我们稍后再谈,它大约是当下开源社区治理模型最大的货物崇拜源头。

TiKV 的 SIG 机制与 Kubernetes 原装的有所不同。它大致是在 TiKV 社区高速发展阶段,临时以当时社区人员的职责分配的快照为基础建立的一种治理模式。问题在于,当时的社区人员大多是创始公司 PingCAP 一家的员工,而职责分配很大程度上跟公司内部的行政结构有关。

提案原文写到

We should decouple community governance from the enterprise organizational structure where SIG is born. Because the community governance reflects the community itself and the evolution. SIG Engine exists because there is a component, not because there is a team inside a company working for it.

实际情况就是,公司内部有一个团队在做存储引擎的工作,所以 SIG Engine 就诞生了。这个组织是被决定诞生的,它的成员也是一夜之间被通知获得权限。这种非自然的组织生长方式导致的一个后果就是,它的成员对社区的投入没有经过考验,也未必熟悉开源协同的工作方式。

SIG Engine 自成立以来仅发展了一位不同背景的 reviewer 成员,哪怕算上相同公司背景的新成员,也只有额外三名 committer 成员。然而,项目的开发仍然有贡献者的参与。对于相同公司背景的贡献者,他们能够通过公司渠道推动有权限的成员合并代码,因此并不在乎 TiKV 社区的治理模式,SIG 名存实亡。对于没有公司渠道的贡献者,他们的贡献则很难被察觉和认可,从而无法融入社区。

行政结构映射成社区治理模式映射还会带来另外两个问题,也就是我在其他场合常说的阻抗失配。

开源社区依托于它制造的软件,治理模式也应该围绕软件来开展。通过项目或者代码模块来划分治理组织,能够保证治理模式与其所治理的开源社区依托的软件之间符合康威定律,从而是稳定的。阻抗失配的第一个表象,是公司行政结构的改变和软件代码架构的演进缺乏明确关联。TiKV 作为键值数据库,在发展过程当中逐渐有了数据同步的需求,相当一部分同学参与了 TiKV CDC 相关的工作,但是他们的工作显然无法顺利的归纳到任何一个当时现行的 SIG 当中。

这其中当然有部分是社区治理缺乏及时重新评估的问题,但是根本上是相关同学归属于 TiKV 与 TiDB 生态整体的数据同步和迁移的团队,与关注到 TiKV 作为存储引擎的团队是两拨人所导致的。这里我们还没谈到社区成员背景多样性的问题。社区治理本该避免社区成员派系化,确保大家都遵守相同的规则,然而在这里却明显力有未逮。

阻抗失配的第二个表现,是治理模式粒度与代码组织粒度的冲突。GitHub 托管的项目,或者说使用 Git 做版本管理的项目,公认的项目组织单位是代码仓库,但是 tikv/tikv 却由好几个 SIG 共同负责。

由于 SIG 与权限挂钩,实际上决定了一个 PR 应该由谁合并,这首先导致了社区协作流程的复杂性。绝大部分开发者的认知是 GitHub 预设的代码仓库粒度的权限模型,然而在 tikv/tikv 中,却有可能出现同一个人能合并一个 PR 而不能合并另一个 PR 的情况。不管它背后有什么逻辑来支撑这件事情,它都带来了额外的复杂度,而没有什么明显的好处。

这样的 bad case 比比皆是。例如一个改动可能同时涉及 SIG Raft 和 SIG Engine 相关的改动,或者更常见的,在 TiDB 社区相似的治理模式下,pingcap/tidb[8] 的一个改动涉及 SIG Planner 和 SIG Execution 的改动,这种情况下社区规则其实允许任意一个 SIG 的成员 review 和 merge 代码。极端情况下,在 PR 未被分配 SIG 的情况下,任何 SIG 的成员都可以 review 和 merge 代码。更不用说在实际规则下社区的 reviewer 和 committer 以群体的“智慧”琢磨出了好几种绕过 SIG 约束的手段。社区成员不免会疑惑,我们费劲地去区分 SIG 为了什么呢?难道我们设定规则,只是为了阻拦我们日常社区事务的进行吗?

最后,社区中的 SIG 其实都设立了章程,然而章程的内容却饱受诟病。

第一,角色定位不明确。实际上 Leader 和 CoLeader 是一个意思,有些 SIG 同时有复数 Leader 成员,那要 CoLeader 这个角色干嘛?另外,Active Contributor 没有任何权限,而且很容易从 commit history 或者 GitHub 的 Contributor Insights 里看到,为啥要在章程里专门罗列这样的角色?SIG 的角色算上 contributor 足足有六种,相比之下,Apache 基金会的项目官方只规定了 committer 和 PMC member 两种。哪怕有些项目为了吸引贡献者或者降低首次激励的门槛设立了 reviewer 角色,也就三种。

第二,部分从 Kubernetes 照搬的机制被证明是无效的,例如每周例会。尤其是把一个代码仓库拆成好几个 SIG 以后,经常每周没啥好聊的,例会几乎成了社交恐惧症患者公开处刑场所。其实很快就不搞这种货物崇拜了,但是相关描述至今仍在,无人收拾。

第三,晋升规则并未实践或者本身就很离谱。举例说明

Effectively reviewing code over 200 lines of code.

真的无力吐槽。其实也是照搬 Kubernetes 的要求,这个跟因地制宜的主题有关,后面篇幅再展开分析。

第四,退出机制不明确。这实际也成为了部分活跃在社区的 Leader 成员犹豫发展新成员的原因,虽然社区基于信任传递原本应该做乐观假设。

第五,章程是全中文的,无力吐槽。社区成员对此最无情的问法就是

Does the community exist in China only?

Working Group

这个也是从 Kubernetes 照搬的机制,原本的作用是通过社区的影响力和传播渠道对一些开发项目形成的工作组进行曝光和吸引贡献者,但是由于 TiKV 社区受限于人力的因素,并没有能力为 WG 提供此类帮助或其他帮助,实际上搞 WG 的形式只是要写一堆材料而已。很快,也就没人搞这个了。

不过 WG 这个概念是客观存在的,软件开发很少是一个人的工作,而一群工作在相同模块,开发同一个功能的人总有某种办法相互联系,其实这就是 SIG 和 WG 的起源。不过要求 WG 写各种申请材料,Zoom 每周例会,做定期报告,就太傻了。

TiDB

Proposal: Lightweight and GitHub Friendly Special Interest Group[9]

TiKV 社区和 TiDB 社区的治理模式在 SIG 和 WG 上大同小异,因此也有相同的问题,不再赘述。TiDB 社区的提案,就是针对同类问题的说明和提议的解决方案。

不同之处在于不像 TiKV 社区覆盖整个社区所有代码仓库的权限重组,仅关注到极其复杂的 pingcap 组织下核心开源软件仓库的治理。同时避开了 TiDB 社区中其他成员为孵化器和技术指导委员会进行的相关工作的话题,首先关注到每一位社区成员在现有的开源软件项目上贡献的的体验。

Solution

针对解决方案,这里做一个概述。背后的原因在下一节 The Rationale 再一并讨论。

Working Group

WG 基本是被社区成员所舍弃的形式,直接废弃即可。唯一的不同是 TiDB 社区历史上存在的 WG 不少,资料需要归档。

Special Interest Group

代码仓库的问题也可以归结为 SIG 的问题,因为代码仓库的问题是责任人不明,而合理的责任人就是某个 SIG 的全体成员。

SIG 的第一个问题是前面提到的阻抗失配,因此两个提案都通过某种形式的 SIG 合并来适配治理模型和代码仓库的物理组织形式,以示区别,将合并后的形式称为团队。

•一个团队有多个成员,分为 reviewer,committer 和 maintainer 三种角色,权责递进。这也简化了原本的六类角色模型,active contributor 被抛弃,两种 leader 合并,以 maintainer 称呼。•一个团队拥有一个或多个代码仓库,权限以团队为粒度分发。这样,现在一个 reviewer 在同一个仓库里的权限就是一致的了。

举个例子,TiKV 社区的 TiKV 团队由原来 SIG Engine,SIG Transaction 和 SIG Coprocessor 合并而来,拥有 tikv/tikv 和 tikv/client 等几十个仓库。其中的 committer 不加区分地有权在这些仓库上合并代码。

SIG 的第二个问题是饱受诟病的章程,所以在提案中只突出了投票决议的流程,其他章程都废弃掉。这些章程本来也没有很好地在运转。当然,指导贡献者参与的原则以及社区在寻找什么样的贡献者是需要持续由 maintainers 总结输出的。

SIG 的第三个问题是成员参与度不高,这与它是被决定诞生,成员是被通知上任的有关。为了解决这个问题,一方面,重组治理模型的行动是公开的,并且广泛通知到每一位关系人士;另一方面,团队成员的发展明确是每位 maintainer 的责任,所有团队成员都需要关注,同时晋升的提名,投票和接受也大部分由团队自驱,从而加强参与感,并实践开源协同的工作方式。

SIG 的第四个问题是深受不完全的自动化的困扰,导致实际权限的执行有种种问题。这部分是 Community Infra 的工作,涉及技术细节不做展开,可以参考提案原文。

Rationale

可以看到,这些问题的诞生很大程度上归咎于对 Kubernetes 社区不加选择的模仿。

《社区运营的艺术》在提及流程与治理时,多次强调应该保持简单,避免形式主义。流程应当是简单的。简单化的对立面,就是复杂化。复杂流程是丑陋的怪兽,它们只会带来形式主义。形式主义是敌人,它会像硫酸一样,腐蚀我们强烈推崇的开源社区所产生的机会、潜力和信念。

Kubernetes 的治理模型是及其复杂的,茫茫多的 SIG 和侵入到代码树每一个层面的 OWNERS 文件,SIG 章程和 WG 等等也是 Kubernetes 社区造物。你以为我会说它的治理模型是错的吗?不,我认为这一模型恰好符合了 Kubernetes 社区的需要。

Kubernetes 的核心逻辑并不复杂,并且作为一个主打容器编排的一揽子运维方案,它的每个部分都是高度插件化的。可以说,模块与模块之间耦合很低,API 和 SPI 很多,实现 SPI 和丰富 API 的案例场景,大力发展生态连接是 Kubernetes 社区的目标。所以,Google 等公司投入大量人力发展社区,维护数以百计的 OWNERS 文件,协调海量的社区治理事务。对 Kubernetes 来说,核心功能早已实现,社区就是目的,生态就是成功。气氛组的广告效应,实际客观技术门槛较低的易用性和生态连接,都能为 Kubernetes 社区带来可观的收益。

我们回过头来看刚才口诛笔伐的那些问题。

Working Group

WG 被社区成员所舍弃?Kubernetes 社区的 WG 可不是这样。

Kubernetes 社区的影响力和专注于社区运营的人数保证你的 WG 有人关注,有人推送,有人宣传,再不济任务结束或者生命终结可以回收。另外,Kubernetes 的 WG 都是非常 General 的,例如可靠性工作组,命名工作组,策略工作组,等等。TiDB 和 TiKV 对 WG 的理解基本停留在功能特性小组的层面。这种需求通过项目内的功能设计提案和 tracking issue 等形式发起和追踪即可。

Special Interest Group

SIG 治理模型和 GitHub 代码仓库模型不匹配。

首先,Kubernetes 社区没有把行政模型映射到社区治理模型上。其次,由于 Kubernetes 项目的性质,核心逻辑并不复杂,模块较好划分,模块和模块之间基本走接口,而且茫茫多的 OWNERS 文件有人维护,出点什么问题有人协调。

TiDB 和 TiKV 作为数据库软件,模块和模块之间的设计关联较大,基本你要支持一个 SQL 语法,从 Parser 到 Planner 再到 Execution 以及其他方方面面的相关代码都会有所影响,这是数据库软件的固有复杂性。即使模块之间拆分的比较好,数据库内核整体相互关联的特点还是很难改变。同样的,TiKV 在 Raft Storage 上的工作,也会涉及 Raft 算法和 Engine 两方面相关的工作,说不定还牵扯到 Transaction 的工作,又因为动了存储逻辑,可能数据同步也要适配。于是 TiDB 和 TiKV 社区把 WG 理解成这种情况下跨 SIG 合作的机制,就回到了上一段提到的问题。总之,社区的贡献者对这种人为的划分基本很不感冒。

关于这一点,还可以结合 Apache 基金会的模式来讨论。其项目治理模型所要求的只有 committer 和 PMC member 两个角色,少数例如 Apache TVM 这样的项目为了降低首次激励的门槛设置了 reviewer 角色,一共也就三个角色。那么,在这些项目当中,SIG 就不存在吗?

答案是否定的。大型项目总会区分模块,模块的专家集合在一起就是一个客观存在的 SIG 式的群体。然而,《社区运营的艺术》对流程和治理的指导性意见就是,简单是王道。是不是一个客观存在的群体就一定要跟权限和社区治理模型结合起来呢?要知道,绝大多数社区成员并不喜欢做这些事务,相比之下他们更期待开发有趣的 feature 或者进行一次沁人心脾的代码重构。

Apache Flink 拥有近十个代码仓库,Flink SQL / State Backend / Runtime / Network / Deployment / High Availability / PyFlink / Connectors 等等模块数不胜数,然而整个社区仍然只有 committer 和 PMC member 两种角色。SIG 的拥护者也许会说,SIG 带来了更细粒度的权限控制。但是开源社区强调的是信任、开放和协作,而不是公司式的权限管控和管理。

Flink 的 committer 不会合并自己无法判断是否会影响软件质量的代码,实际上这也是 TiDB Dev Guide 里对代码评审的要求。反过来,对于明显有益无害的贡献,例如修正拼写错误或者可以证明的代码重构,只需要基本的软件开发知识就可以判断和合并。这一方面避免了 TiDB 社区里,一个明显正确的改动“不幸”命中了一个活跃 committer 稀少的 SIG 的标签,其他活跃的 committer 只能点出无效的赞而无能为力的情况;另一方面,它鼓励了 committer 关注不同模块的贡献,甚至在闲暇时间花点力气了解和评审稍微复杂的其他模块的贡献,从而成为更加全能的社区成员。SIG 分裂代码仓库以及各个 OWNERS “国界线”界定下,不同社区成员的领地意识会被强化,大多数社区并没有 Kubernetes 社区那么庞大的人力来协调领地意识带来的种种问题。

Constitution

TiDB 社区里看似无厘头的 SIG 章程,在 Kubernetes 社区里是可以成立的。

还是因为核心逻辑,工作可量化的原因。这种类似于计件工作制的章程成立的前提是工作内容可量化。由于 Kubernetes 核心逻辑简单,PR 的难度大同小异,这么规定至少是可以解释的。哪怕难度有差别,也可以真的标出可以量化的难度来衡量。

基础软件的开发,难度衡量几乎是没有意义的。除了乍一看没啥门槛的 good first issue 和其他问题以外,任何试图进一步分级的行为都会出问题。因为不像 Kubernetes 调整接口调用方式的工作,或者前端组合控件实现功能的工作,大型基础软件的内在逻辑足够复杂,经常一个问题乍一看很简单,结果越做越难,掉进坑里,或者乍一看很难,经过一个下午的分析发现其实是一行代码的问题。你可以辩护说这种情况下可以调整难度的标记,但是原本是创建 issue 时就能几乎确定的难度,现在变成了需要专家动态评估的难度,专家的时间非常宝贵,我是社区成员,我不希望他们整天干这种事。

Process Reassessment

《社区运营的艺术》提到,流程都是有生命,有呼吸的有机体。它们通常是由当前的条件决定的,包括当前贡献的水平,要求,期望和目标。它们是一层透明的塑料薄膜,里面包裹着社区里的资产和成员。随着资产和成员的调整,流程也需要调整。

本文对 TiKV 和 TiDB 社区在当下对现行流程和治理模型的重新评估做了分析和讨论,但是新提出的方案也不会是一成不变的。随着时间的流逝,我们需要不断的重新评估流程,一成不变的流程会导致形式主义。当流程不再能够有效地反应那些需要使用它的人们的需求时,就会导致形式主义。《社区运营的艺术》对重新评估的手段结合 Ubuntu 社区的实践做了详细的介绍,篇幅较长且内容独特,这里不做引用,推荐阅读。

回到标题,开源社区的治理模型应当因地制宜,其动态形式就是对流程和治理模型的不断重新评估。本文以 TiDB 和 TiKV 两个开源社区重新评估自己的治理模型为案例,尤其在最后这一章当中分析了不同情况下因地制宜的判断方式,希望能为越来越多的新兴开源社区提供开源社区的治理模型方面的经验。

Others

最后,作为尾声略带一提的是,流程与治理模型至多是社区运行的框架,开源社区通过其成员所生产的软件,内容,合作案例和经验产生价值。TiDB 和 TiKV 社区在流程与社区治理之外,还为社区发展推动了内容和代码方面的两个项目。

TiDB Development Guide[10]

第一个是内容方面的 TiDB 开发者指南,通过四个章节介绍了参与贡献 TiDB 数据库内核所需要了解的知识。

•Get Started 介绍了准备环境,下载代码到开发一个补丁的全流程。•Contribute to TiDB 首先介绍了社区指导原则,随后针对 issue 报告,功能开发和文档撰写等典型贡献流程做了细致的讲解。•Understanding TiDB 是一个尚在撰写的章节,脱胎于源码阅读系列,介绍了 TiDB 各个模块的设计与实现。•Project Management 则包括 TiDB 的开发活动组织形式和发布周期等项目关系相关的内容。

贡献者参与社区的两个核心问题是

1.我能为这个社区做什么?2.我应该怎么做到想做的事?

Dev Guide 的四个章节共同引导贡献者自主解决这两个问题。

Tracking issue for restructure tests[11]

如何参与改善 TiDB 代码质量?我是说...一分钟成为 TiDB 贡献者。[12]

第二个是代码方面的 TiDB 测试框架迁移项目,如果对参与 TiDB 感兴趣,可以从项目的 tracking issue 和我制作的介绍视频入手了解。

预计分成三个阶段。

•第一阶段是确定迁移基调,迁移依赖较少的实用函数模块,目前已经完成了。•第二阶段是攻坚核心代码模块,包括 ddl / executor / expression / planner 等等,目前已经逐步开展起来了。•第三阶段是收尾和清理脚手架,这个到第二阶段越过临界线之后会开始推进。

一方面,这个项目通过测试这种目标明确的工作帮助贡献者跨过参与贡献的门槛,成为给社区提交过代码的一份子。另一方面,对于积极的贡献者来说,这其实是一个广阔天地的窗口。这个项目从代码层面上涉及了 TiDB 数据库核心的方方面面,只要你愿意花时间研究迁移的测试代码以及背后的生产代码的逻辑,找到可做的工作,深入的参与社区不是一件难事。

另外,一旦有了进入社区的主观感受,也可以参与到上面提到的 Dev Guide 或者其他项目当中去,成为社区的明星。

References

[1] 《社区运营的艺术》: https://book.douban.com/subject/26976995/
[2] Proposal: Reduce the Entropy of TiKV Community Governance: https://github.com/tikv/community/issues/118
[3] tikv/tikv: https://github.com/tikv/tikv
[4] tikv/raft-rs: https://github.com/tikv/raft-rs
[5] tikv/pd: https://github.com/tikv/pd
[6] tikv/rust-prometheus: https://github.com/tikv/rust-prometheus
[7] tikv/client-java: https://github.com/tikv/client-java
[8] pingcap/tidb: https://github.com/pingcap/tidb
[9] Proposal: Lightweight and GitHub Friendly Special Interest Group: https://github.com/pingcap/community/issues/516
[10] TiDB Development Guide: https://pingcap.github.io/tidb-dev-guide/
[11] Tracking issue for restructure tests: https://github.com/pingcap/tidb/issues/26022
[12] 如何参与改善 TiDB 代码质量?我是说...一分钟成为 TiDB 贡献者。: https://www.bilibili.com/video/BV1cM4y1T7D8/


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存